//#define USE_DUNGEONBUDDY_DLL
using System.Collections.Generic;
using System.Linq;
using Styx;
using Styx.CommonBot;
using Styx.Pathing;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
#if USE_DUNGEONBUDDY_DLL
using Bots.DungeonBuddyDll;
using Bots.DungeonBuddyDll.Attributes;
using Bots.DungeonBuddyDll.Helpers;

namespace Bots.DungeonBuddyDll.Dungeon_Scripts.Burning_Crusade
#else
    using Bots.DungeonBuddy.Attributes;
    using Bots.DungeonBuddy.Helpers;
namespace Bots.DungeonBuddy.Dungeon_Scripts.Burning_Crusade
#endif

{
    public class Underbog : Dungeon
    {
        #region Overrides of Dungeon

        public override uint DungeonId
        {
            get { return 146; }
        }

        public override void RemoveTargetsFilter(List<WoWObject> units)
        {
            units.RemoveAll(
                unit =>
                {
                    // remove Ghaz'an if swiming around.
                    if (unit.Entry == GhazanId && unit.Z < 70)
                        return true;
                    return false;
                });
        }


        public override void WeighTargetsFilter(List<Targeting.TargetPriority> units)
        {
            foreach (var targetPriority in units)
            {
                switch (targetPriority.Object.Entry)
                {
                    case MurkbloodHealerId:
                        if (StyxWoW.Me.IsDps())
                            targetPriority.Score += 220;
                        break;
                }
            }
        }

        #endregion

        private const uint GhazanId = 18105;
        private const uint MurkbloodHealerId = 17730;
        private readonly WoWPoint _ghazanFollowerWaitSpot = new WoWPoint(162.3641, -445.7501, 72.43507);
        private readonly WoWPoint _ghazanTankSpot = new WoWPoint(152.2157, -467.3924, 75.0878);
        private WoWUnit _hungarfen;

        private LocalPlayer Me
        {
            get { return StyxWoW.Me; }
        }

        [EncounterHandler(0)]
        public Composite RootBehavior()
        {
            return new PrioritySelector(
                // don't get stuck swimming.
                new Decorator(ctx => Me.IsSwimming && Me.X < 160 && !Me.Combat, new Action(ctx => ScriptHelpers.TelportOutsideLfgInstance())));
        }

        [EncounterHandler(54678, "Naturalist Bite", Mode = CallBehaviorMode.Proximity, BossRange = 30)]
        [EncounterHandler(54674, "T'shu", Mode = CallBehaviorMode.Proximity, BossRange = 30)]
        public Composite QuestPickupHandler()
        {
            WoWUnit unit = null;
            return new PrioritySelector(
                ctx => unit = ctx as WoWUnit,
                new Decorator(
                    ctx => !Me.Combat && !ScriptHelpers.WillPullAggroAtLocation(unit.Location) && unit.QuestGiverStatus == QuestGiverStatus.Available,
                    ScriptHelpers.CreatePickupQuest(() => unit)),
                new Decorator(
                    ctx => !Me.Combat && !ScriptHelpers.WillPullAggroAtLocation(unit.Location) && unit.QuestGiverStatus == QuestGiverStatus.TurnIn,
                    ScriptHelpers.CreateTurninQuest(() => unit)));
        }

        [EncounterHandler(17770, "Hungarfen")]
        public Composite HungarfenEncounter()
        {
            const uint underbogMushroomId = 17990;

            AddAvoidObject(ctx => !Me.IsCasting, 10, underbogMushroomId);

            return new PrioritySelector(ctx => _hungarfen = ctx as WoWUnit, ScriptHelpers.CreateSpreadOutLogic(ctx => true, () => _hungarfen.Location, 10, 30));
        }


        [EncounterHandler(18105, "Ghaz'an", Mode = CallBehaviorMode.Proximity, BossRange = 105)]
        public Composite GhazanEncounter()
        {
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                // pull boss. check if he's not in the water first.
                new Decorator(
                    ctx => StyxWoW.Me.IsTank() && (Targeting.Instance.IsEmpty() || Targeting.Instance.FirstUnit.Entry == GhazanId) && boss.Z > 70 && Me.Y < -435,
                    new Sequence(
                        new DecoratorContinue(ctx => Me.CurrentTargetGuid != boss.Guid,
                            new Action(ctx => boss.Target())),
                        ScriptHelpers.CreateMoveToContinue(ctx => boss.Distance > 30, () => boss, false),
                        ScriptHelpers.CreateCastRangedAbility(),
                        ScriptHelpers.CreateMoveToContinue(() => _ghazanTankSpot))),
                // wait for tank to move in place.
                ScriptHelpers.CreateWaitAtLocationUntilTankPulled(ctx => StyxWoW.Me.Location.DistanceSqr(_ghazanFollowerWaitSpot) < 15 * 15, () => _ghazanFollowerWaitSpot),
                ScriptHelpers.CreateAvoidUnitAnglesBehavior(
                    ctx => !Me.IsTank() && boss.Distance < 20 && boss.CurrentTargetGuid != Me.Guid,
                    () => boss,
                    new ScriptHelpers.AngleSpan(0, 100),
                    new ScriptHelpers.AngleSpan(180, 100)),
                new Decorator(ctx => boss.CurrentTargetGuid == Me.Guid && Me.IsTank(), ScriptHelpers.CreateTankUnitAtLocation(() => _ghazanTankSpot, 5f)));
        }

        [LocationHandler(233.7793, -476.9487, 48.93488, 100, "Handle swimming to pool exit just after Ghaz'an")]
        public Composite GetOutOfWaterBehavior()
        {
            var poolExitLoc = new WoWPoint(333.1345, -471.5125, 52.07739);

            return new PrioritySelector(
                new Decorator(ctx => Me.IsSwimming,
                    new Action(ctx => Navigator.PlayerMover.MoveTowards(poolExitLoc))));
        }

        /*
        [EncounterHandler(18105, "Ghaz'an", Mode = CallBehaviorMode.Proximity, BossRange = 105)]
        public Composite GhazanEncounter()
        {
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                // pull boss. check if he's not in the water first.
                ScriptHelpers.CreatePullNpcToLocation(
                    ctx => boss.Z > 70f && !ScriptHelpers.GetUnfriendlyNpsAtLocation(() => Me.Location, 60, u => u.Z > 50 && u.Entry != GhazanId).Any(),
                    ctx => true,
                    () => boss,
                    () => _ghazanTankSpot,
                    () => _ghazanFollowerWaitSpot,
                    6),
                // avoid the front and back.
                ScriptHelpers.CreateAvoidUnitAnglesBehavior(
                    ctx => !Me.IsTank() && boss.Distance < 20, () => boss, new ScriptHelpers.AngleSpan(0, 100), new ScriptHelpers.AngleSpan(180, 100)));
        }

         */

        [EncounterHandler(17826, "Swamplord Musel'ek", Mode = CallBehaviorMode.Proximity, BossRange = 100)]
        public Composite SwamplordMuselekEncounter()
        {
            return new PrioritySelector(
                ScriptHelpers.CreateClearArea(() => new WoWPoint(214.0852, -131.6859, 27.32064), 50f, u => u.Entry == 17734) // kill the Underbog Lord
                );
        }

        [EncounterHandler(17882, "The Black Stalker")]
        public Composite TheBlackStalkerEncounter()
        {
            return new PrioritySelector(
                ScriptHelpers.CreateSpreadOutLogic(ctx => true, () => ScriptHelpers.Tank.Location, 13, 30f) // spread out
                );
        }
    }
}